package exercise;

import equation.*;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;

public class ExerciseGenerator {
    // 自己创建自己的唯一实例
    private static final ExerciseGenerator instance = new ExerciseGenerator();
    // 构造函数私有限制，实现单实例模式
    private ExerciseGenerator() {
    }
    // 对外界提供唯一的方法获取实例
    public static ExerciseGenerator getInstance() {
        return instance;
    }

    public Exercise generate(int number, EquationRangeChecker equationRangeChecker) {
        // 创建exercise对象
        Exercise exercise = new Exercise();
        // 哈希集合保证算式不重复
        HashSet<Equation> hashSet = new HashSet<>();
        EquationFactory equationFactory = new EquationFactory();
        Random random = new Random();
        // 整除检查器
        ExactDivisionChecker exactDivisionChecker = new ExactDivisionChecker();
        // 通过单元测试和系统测试发现了一个问题：
        // 产生的加法算式和减法算式远多于乘法和除法算式
        // 采用如下方式可初步解决
        // mark是一个标记数组，将number粗等分为四份，记录每种算式应产生的数量
        // 以此控制输出的算式尽可能数量均等
        Integer[] mark = {number - number*3/4, number/4, number/4, number/4};
        while (number != 0) {
            // 这个数组用于使用工厂模式创建Equation的对象
            String[] keyWords = {"AddEquation", "SubEquation", "MultiplyEquation", "DivideEquation"};
            Integer operandA = random.nextInt(equationRangeChecker.getUpperLimit() - equationRangeChecker.getLowerLimit()+1) + equationRangeChecker.getLowerLimit();
            Integer operandB = random.nextInt(equationRangeChecker.getUpperLimit() - equationRangeChecker.getLowerLimit()+1) + equationRangeChecker.getLowerLimit();
            int keyWordIndex = random.nextInt(4);
            // 利用工厂创建Equation对象
            Equation equation = equationFactory.getEquation(keyWords[keyWordIndex], operandA, operandB);
            // mark数组所剩值是否为0检查
            if (mark[keyWordIndex] == 0) {
                continue;
            }
            // 检查哈希集合里是否已存在此算式
            // 注：使用此方法，Equation须重写hashNode和equals方法，不然有可能出错
            if (hashSet.contains(equation)) {
                continue;
            }
            // 对除法进行整除检查
            if (keyWords[keyWordIndex].equals("DivideEquation") && !(exactDivisionChecker.check(equation))) {
                continue;
            }
            // 对所有算式进行范围检查
            if (equationRangeChecker.check(equation)) {
                hashSet.add(equation);
                // 每添加一个算式，将对应mark数组的值减一
                mark[keyWordIndex]--;
                number--;
            }
        }
        exercise.setData(new ArrayList<>(hashSet));
        return exercise;
    }

}
